package com.atxiaodei.nio.nioday01;

import org.junit.Test;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @author wangmeng
 * @date 2020/9/19
 *       在学习Stream对map排序之前，我们先要搞清楚，map的实例hashmap是无序的，LinkedHashMap 是有序的
 *      所有呢，在创建一个hashmap实例时，我们进行了排序返回的实例应该是LinkedHashMap
 *
 *      LinkedHashMap来存储排序的结果以保持顺序。默认情况下，Collectors.toMap()返回HashMap。HashMap不能保证元素的顺序。
 **/
public class StreamApi12Map排序 {

    /**
     * 在学习Map排序之前，有必要讲一下HashMap的merge()函数，该函数应用场景就是当Key重复的时候，如何处理Map的元素值。这个函数有三个参数：
     *
     * 参数一：向map里面put的键
     * 参数二：向map里面put的值
     * 参数三：如果键发生重复，如何处理值。可以是一个函数，也可以写成lambda表达式。
     */
    @Test
    public void test1(){
        String k = "key";
        HashMap<String, Integer> map = new HashMap<String, Integer>() {{
            put(k, 1);
        }};
        Integer merge = map.merge(k, 2, (x, y) -> x + y);
        System.out.println(merge);// 输出 3
        System.out.println(map);// 输出 {key=3}
        /**
         * 总结：
         *       上述：   表达式的含义是：返回 旧值x加上 新值y (1+2)，现在map里面只有一项元素那就是k:3。
         *      随之想象，map在使用merge()函数时候，当key发生重复的时候，map更新的value值是我们指定的lamdba表达式返回的值
         *
         *      应用场景呢：实际开发当中我们有很多更新map中某一个或者多个键值对应的值的计算了（原有的基础上增加了 相互乘积了等运算），
         *      这会我们也就不用获取了，直接使用merge()函数了来更新它的值了
         *
         *      也可以遐想下一下，我们学过的版本控制 svn git 里面那个merge不就是合并的意思吗，总要你有个选择的版本的，替换原来的冲突
         *      的代码的
         *
         *
         */

    }

    /**
     * 按map的键排序
     *
     */
    @Test
    public void test2(){
        // 创建一个Map，并填入数据
        Map<String, Integer> codes = new HashMap<>();
        codes.put("United States", 1);
        codes.put("Germany", 49);
        codes.put("France", 33);
        codes.put("China", 86);
        codes.put("Pakistan", 92);
        codes.put("Pakistan", 100);
        // 按照map的键进行排序
        Map<String, Integer> collect = codes.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                // .sorted(Map.Entry.comparingByValue()) // 按照map的value排序
                .collect(Collectors.toMap(Map.Entry::getKey,
                        Map.Entry::getValue,
                        (x,y)->y,
                        LinkedHashMap::new));
        System.out.println(collect);

        collect.entrySet().forEach(System.out::println);
        /**
         * 总结：首先使用entrySet().stream() 将Map类型转换为Stream流类型。
         * 然后使用sorted方法排序，排序的依据是Map.Entry.comparingByKey()，也就是按照Map的键排序
         * 最后用collect方法将Stream流转成LinkedHashMap。
         * 其他参数都好说，重点看第三个参数，就是一个merge规则的lambda表达式，与merge方法的第三个参数的用法一致。
         * 由于本例中没有重复的key，所以新值旧值随便返回一个即可。
         */
    }

    /**
     * 在我们学习之前的jdk的时候学习TreeMap的时候，就是TreeMap内的元素是有顺序的，
     * 所以利用TreeMap排序也是可取的一种方法。您需要做的就是创建一个TreeMap对象，
     * 并将数据从HashMap put到TreeMap中
     * 这种方式 排序Map集合很方便
     */
    @Test
    public void test3(){
        Map<String, Integer> codes = new HashMap<>();
        codes.put("United States", 1);
        codes.put("Germany", 49);
        codes.put("France", 33);
        codes.put("China", 86);
        codes.put("Pakistan", 92);
        TreeMap<String, Integer> treeMap = new TreeMap<>(codes);
        treeMap.entrySet().forEach(System.out::println);
    }


}
